#!usr/bin/env python  
# -*- coding:utf-8 _*-
""" 
@author:robot
@file: v2_api_base.py 
@version:
@time: 2022/03/01 
"""
import json
from time import sleep
import requests
from TapUtil.logfunc.logger import logger
from TapClientCore.T01_init_conf.v2_init.init_config import requests_retime
from TapClientCore.T01_init_conf.v2_init.init_config import is_use, is_method, is_url, is_header, is_payload, \
    is_response
from TapClientCore.T02_tm_api.v2_api.v2_api_url_base import *
from TapException.TM import *

urlbase = V2ApiUrlBase()


class V2ApiBase:
    get = 'GET'
    post = 'POST'
    patch = 'PATCH'
    delete = 'DELETE'
    put = 'PUT'
    # dfs connect.sid
    test_connect_sid = None
    product_connect_sid = None
    # for requests
    serve = urlbase = session = cookies = access_token = access_token2 = ws_uri = Xtoken = None
    # for tapdata
    server, setting, user, user_id, tapdata_production, _api = None, None, None, None, None, None
    # for this
    ERROR = False

    def __init__(self):
        self.setting = config
        self.serve = config.get('serve')
        self.apiserve = config.get('apiserve')
        self.test_connect_sid = config.get('dfs_test').get('cookies').get('value')
        self.product_connect_sid = config.get('dfs_production').get('cookies').get('value')
        if self.session is None:
            self.session = requests.session()
            self.session.headers.update({'content-type': 'application/json'})
            self.session.headers.update({'accept': 'application/json'})
        self.login_auth()

    @staticmethod
    def _code_check(response):
        code = response.json().get('code')
        if code:
            if code != 'ok':
                if code == 'Datasource.RepeatName':
                    raise DataSourceRepeatName
                elif code == 'Task.RepeatName':
                    raise TaskError
                elif code == 'Task.DeleteTimeout':
                    raise TaskDeleteTimeout
                else:
                    logger.info(response.json())
                    raise RequestError
        else:
            logger.warning('not code attr')

    def tapclient(self, method, url, **kwargs):
        COUNT = 0
        response = None
        while True:
            try:
                if is_use:
                    response = self.session.request(method, url, **kwargs)
                    if is_method:
                        logger.info(f'01 METHOD: {method}')
                    if is_url:
                        logger.info(f'02 URL: {url}')
                    if is_header:
                        logger.info(f'03 REQUEST HEADER: {response.request.headers}')
                    if is_payload:
                        logger.info(f'04 REQUEST BODY: {response.request.body}')
                    if is_response:
                        logger.info(f'05 REQUEST RESPONSE: {response.text}')
                    self._code_check(response)
                    return response.json()
                else:
                    response = self.session.request(method, url, **kwargs)
                    self._code_check(response)
                    return response.json()
            except Exception as e:
                logger.warning(e)
                logger.fatal('requests error')
                COUNT += 1
                if COUNT == requests_retime:
                    self.ERROR = True
                    raise e
                sleep(1)
                continue

    def login_auth(self):
        if self.serve in ['http://test.cloud.tapdata.net']:
            self.dfs_auth('test')
        elif self.serve in ['https://cloud.tapdata.net']:
            self.dfs_auth('production')
        else:
            self.daas_auth()

    def dfs_auth(self, env):
        if self.ERROR is False:
            self.dfs_login(env)
            self.dfs_ws(env)
            self.tapdata_production = 'dfs'
            self.access_token = ''
        else:
            raise RequestError

    def dfs_login(self, env):
        _url = api_joint(self.serve, 'console/api/tcm/user')
        if env == 'test':
            raw_cookies = self.test_connect_sid
            self.cookies = {'connect.sid': raw_cookies}
            self.user = config.get('dfs_test').get('loginInfo').get('user')
        elif env == 'production':
            raw_cookies = self.product_connect_sid
            self.cookies = {'connect.sid': raw_cookies}
            self.user = config.get('dfs_production').get('loginInfo').get('user')
        self.session.cookies.update(self.cookies)
        response = self.tapclient(
            self.get,
            _url
        )
        if self.ERROR is True:
            return
        else:
            self.Xtoken = {
                'X-Token': response.get('data').get('token')
            }
            self.session.headers.update(self.Xtoken)

    def dfs_ws(self, env):
        if env == 'test':
            ws = self.serve[7:]
            ws = api_joint(
                'ws://',
                ws,
                '/tm/ws/agent',
                division=''
            )
            from TapClientCore.T02_tm_api.api_util.AKSK import ws_params
            self.ws_uri = ws + '?' + ws_params()
        elif env == 'production':
            ws = self.serve[8:]
            ws = api_joint(
                'wss://',
                ws,
                '/tm/ws/agent',
                division=''
            )
            self.ws_uri = ws + '?' + '__token=NjA3Njk1ZTExNDMyYjhmNjBjODk4Mjc1.Y2Y2NDkxMGE5NjIwYjA3MTA4ZTI1NzJkZjQ4OW' \
                                     'Y2OTQ0MTczM2Y4NDViODVmYjhjYjM5ZTkzM2QyZDYxNmYyMA=='

    def daas_auth(self):
        self.server = urlbase.server
        self.user = self.setting.get('user')
        self.daas_login()
        self.daas_ws()
        self.tapdata_production = 'Daas2.0'

    def daas_login(self):
        try:
            response = self.tapclient(self.get,
                                      api_joint(self.server, TIMESTAMP))
            stime = response.get('data')
            str_stime = str(stime)
            email = self.setting.get('email')
            password = self.setting.get('password')
            raw_sign = api_joint(email, password, str_stime, 'Gotapd8', division='')
            sign = tapsha1(raw_sign)
            login_data = {
                'email': email,
                'password': password,
                'stime': stime,
                'sign': sign
            }
            response_login = self.tapclient(self.post,
                                            api_joint(self.server, USERS, USERS_LOGIN),
                                            json=login_data)
            if self.ERROR is True:
                return LoginFailedError
            # 获取id
            access_id = response_login.get('data').get('id')
            user_id = response_login.get('data').get('userId')
            self.access_token = f'?{api_joint("access_token", access_id, division="=")}'
            self.access_token2 = f'&{api_joint("access_token", access_id, division="=")}'
            # session 中更新token
            # self.session.cookies.update(
            #     {
            #         'user_id': user_id,
            #     }
            # )
            # self.user_id = user_id
            # self.cookies = self.session.cookies.items()
        except Exception as e:
            raise LoginFailedError

    def daas_ws(self):
        ws = self.serve[7:]
        ws = api_joint("ws://", ws, "/ws/agent", self.access_token, division="")
        self.ws_uri = ws

    @staticmethod
    def dfs_path_transform(url):
        """
        云版企业版请求路径的变化
        :param url:
        :return:
        """
        _url = url.replace("tm", "console/tm")
        return _url

    # 条件筛选
    def filter(self, p):
        filter = '&filter=' + json.dumps(p)
        if self.tapdata_production == 'dfs':
            filter = '?filter=' + json.dumps(p)
        return filter

    # 条件筛选
    @staticmethod
    def where(p):
        where = '?where=' + json.dumps(p)
        return where

    # 条件筛选
    @staticmethod
    def name(p):
        return '?name=' + p


if __name__ == '__main__':
    i = V2ApiBase()
